package com.openatc.agent.handler;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonSyntaxException;
import com.openatc.agent.model.Permission;
import com.openatc.agent.model.User;
import com.openatc.agent.service.MsgPreStrategy;
import com.openatc.agent.service.PermissionDao;
import com.openatc.agent.service.UserDao;
import com.openatc.agent.utils.ApplicationContextProvider;
import com.openatc.agent.utils.TokenUtil;
import com.openatc.comm.data.MessageData;
import com.openatc.comm.handler.IMsgPreHandler;
import com.openatc.core.model.InnerError;
import com.openatc.core.model.RESTRet;
import com.openatc.core.util.RESTRetUtils;
import com.openatc.model.model.ControlPattern;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.logging.Logger;

import static com.openatc.comm.common.CosntDataDefine.ControlPattern;
import static com.openatc.comm.common.CosntDataDefine.setrequest;
import static com.openatc.core.common.Constants.*;
import static com.openatc.core.common.IErrorEnumImplInner.E_101;
import static com.openatc.core.common.IErrorEnumImplInner.E_102;
import static com.openatc.core.common.IErrorEnumImplOuter.E_3008;
import static com.openatc.core.common.IErrorEnumImplOuter.E_4001;

/**
 * @Classname MsgPreHandler
 * @Description
 * @Date 2022/4/6 14:42
 * @Created by panleilei
 */
@Component
public class MsgPreHandler implements IMsgPreHandler {

    private final static Logger logger = Logger.getLogger(MsgPreHandler.class.getSimpleName());

    private Gson gson = new Gson();

    @Autowired
    private UserDao userDao;

    @Autowired
    private PermissionDao permissionDao;

    private MsgPreStrategy msgPreStrategy;

    @Override
    public RESTRet process(MessageData requestData) {
        String infotype = requestData.getInfotype();
        String operation = requestData.getOperation();
        if (infotype == null) {
            InnerError innerError = RESTRetUtils.innerErrorObj(requestData.getAgentid(), E_102, requestData);
            RESTRetUtils.errorDetialObj(E_4001, innerError);
        }

        if (operation == null) {
            InnerError innerError = RESTRetUtils.innerErrorObj(requestData.getAgentid(), E_101, requestData);
            RESTRetUtils.errorDetialObj(E_4001, innerError);
        }

        // 访客禁止下发任何控制指令（set-request）
        if (setrequest.equals(operation)) {
            // 处理访客请求
            boolean isGuest = processGuest();
            if (isGuest) {
                logger.warning(E_3008.getErrorMsg() + " Agentid :" + requestData.getAgentid() );
                return RESTRetUtils.errorDetialObj(E_3008, new InnerError());
            }

            // 获取当前登录的用户
            String userName = TokenUtil.getCurrentUserName();
            // 获取用户权限
            List<Permission> permissions = permissionDao.getPermissionsByUserName(userName);
            boolean hasPermission = false;
            if (!CollectionUtils.isEmpty(permissions)) {
                // 鉴权
                if (infotype.contains("feature/")) {
                    // 当前用户要有configer:download权限，才能下载特征参数
                    hasPermission = verifyPermission(PERMISSION_FEATURE_DOWNLOAD,permissions);
                } else if (infotype.contains("control/")){
                    // 当前用户要有configer:manual权限，才能下发控制指令
                    hasPermission = verifyPermission(PERMISSION_MANUAL,permissions);
                } else if (infotype.contains("system/")) {
                    // 当前用户要有system权限，才能下发系统相关指令
                    hasPermission = verifyPermission(PERMISSION_SYSTEM,permissions);
                }
            }
//            else {
//                return RESTRetUtils.errorDetialObj(E_3008, new InnerError());
//            }
            if (!hasPermission) {
                logger.warning(E_3008.getErrorMsg() + " Agentid :" + requestData.getAgentid() );
                return RESTRetUtils.errorDetialObj(E_3008, new InnerError());
            }

        }
        // 获取对象的名字
        String beanName = getBeanName(requestData);

        try {
            msgPreStrategy = (MsgPreStrategy) ApplicationContextProvider.getBean(beanName);
        } catch (BeansException e) {
//            logger.warning("This request need not preProcess!");
            return RESTRetUtils.successObj(null);
        }

        return msgPreStrategy.preProcess(requestData);

    }

    /**
     * 验证是否有相关权限
     * @param opPermission
     * @param permissions
     * @return
     */
    private boolean verifyPermission(String opPermission, List<Permission> permissions) {
        for (Permission permission : permissions) {
            // 拥有所有权限
            if ("*".equals(permission.getPermission_code())) {
                return true;
            }
            if (permission.getPermission_code().contains(opPermission)) {
                return true;
            }
        }
        return false;
    }

    private String getBeanName(MessageData requestData) {
        // 下发改变控制方式指令，需做特殊处理
        if (setrequest.equals(requestData.getOperation()) && ControlPattern.equals(requestData.getInfotype())) {

            JsonElement data = requestData.getData();

            ControlPattern controlPattern = null;
            try {
                controlPattern = gson.fromJson(data, ControlPattern.class);
            } catch (JsonSyntaxException e) {
                logger.warning("Json parse failed!");
                return "";
            }

            if (controlPattern == null) {
                return "";
            }

            return requestData.getInfotype() + "-" + controlPattern.getControl();
        }

        return requestData.getInfotype();
    }

    /**
     * 处理访客请求
     * @return
     */
        private boolean processGuest () {
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            if (user == null) { // null代表没有开启shiro
                return false;
            }
            String user_name = user.getUser_name();
            List<String> roles = userDao.getRoleNamesByUsername(user_name);
            if (!CollectionUtils.isEmpty(roles)) {
                // 只有访客角色
                if (roles.size() == 1 && "guest".equals(roles.get(0))) {
                    return true;
                }
            }
            return false;
        }

}
